<template>
  <div
    ref="outer"
    class="scroll-outer"
    @mouseover="onMouseover"
    @mouseleave="onMouseleave"
  >
    <div ref="scrollBox" class="scroll-inner-box">
      <div ref="scrollItemBox" class="scroll-item-box">
        <slot />
      </div>
      <div v-if="showSecond" class="scroll-item-box">
        <slot />
      </div>
    </div>
  </div>
</template>
<script>
export default {
  name: 'MyAutoScroll',
  props: {
    list: {
      type: Array,
      default: () => [
        { name: '张三1' },
        { name: '张三2' },
        { name: '张三3' },
        { name: '张三4' },
        { name: '张三5' },
        { name: '张三6' },
        { name: '张三7' },
        { name: '张三8' },
        { name: '张三9' },
        { name: '张三10' }
      ]
    },
    speed: {
      type: Number,
      default: 0.1
    },
    // 滚动作单步运动时的单纯运动距离
    singleHeight: {
      type: Number,
      default: 0
    },
    // 单步运动的时间间隔
    waitTime: {
      type: Number,
      default: 0
    }
  },
  data() {
    return {
      rafId: null,
      y: 0,
      showSecond: false,
      controleHeight: 0
    }
  },
  watch: {
    list: {
      handler(newVal) {
        var that = this
        this.$nextTick(() => {
          console.log(newVal)
          if (newVal && newVal.length > 0) {
            const scrollBox = that.$refs.scrollBox
            const outer = that.$refs.outer

            if (this.myReq) {
              cancelAnimationFrame(this.myReq)
            }
            // 开启动画
            if (this.canRun()) this.reqAnimationFrame()
            // this.reqAnimationFrame();
            // 手动滚动到底部时滚动条重置到最上边,同时滚动盒子重置为top:0
            outer.addEventListener('scroll', function() {
              if (
                outer.scrollTop + outer.clientHeight + 4 >=
                outer.scrollHeight
              ) {
                outer.scrollTop = 0
                that.y = 0
                scrollBox.style.top = 0
              }
            })
          }
        })
      },
      deep: true,
      immediate: true
    }
  },
  mounted() {
    window.addEventListener('resize', this.listenResizeFn)
  },
  destroyed() {
    window.removeEventListener('resize', this.listenResizeFn)
    cancelAnimationFrame(this.myReq)
    if (this.timer) clearTimeout(this.timer)
  },
  methods: {
    listenResizeFn() {
      cancelAnimationFrame(this.myReq)
      if (this.canRun()) this.reqAnimationFrame()
    },
    onMouseover() {
      clearTimeout(this.timer)
      cancelAnimationFrame(this.myReq)
    },
    onMouseleave() {
      if (this.canRun()) this.reqAnimationFrame()
    },
    canRun() {
      const scrollItemBox = this.$refs.scrollItemBox
      const scrollBox = this.$refs.scrollBox
      const outer = this.$refs.outer
      // 开启动画条件：滚动盒子(scrollBox)高度高于外层容器(outer)高度
      if (outer.offsetHeight >= scrollItemBox.offsetHeight) {
        this.showSecond = false
        outer.scrollTop = 0
        this.y = 0
        scrollBox.style.top = 0
        return false
      } else {
        this.showSecond = true
        return true
      }
    },
    // 获取dom元素的高度：content+padding+margin+border
    getComputedHeight(dom) {
      const computedStyle = getComputedStyle(dom)

      const computedHeight =
        dom.offsetHeight +
        parseFloat(computedStyle.marginTop) +
        parseFloat(computedStyle.marginBottom)
      return computedHeight
    },
    reqAnimationFrame() {
      // 外层容器
      const outer = this.$refs.outer
      // 滚动盒子
      const scrollBox = this.$refs.scrollBox
      // 滚动盒子下边的第一个scroll-item-box，
      const scrollItemBox = this.$refs.scrollItemBox

      // 滚动速度
      this.speed = this.speed > 1 ? 1 : this.speed < 0 ? 0.1 : this.speed

      // 取第一个scrollItemBox高度
      const definedHeight = this.getComputedHeight(scrollItemBox)
      // 持续滚动
      this.y = this.y + this.speed
      scrollBox.style.top = -this.y + 'px'

      // ====添加滚动间隔控制====开始
      if (this.singleHeight >= 20 && this.waitTime > 500) {
        if (this.controleHeight >= this.singleHeight) {
          cancelAnimationFrame(this.myReq)
          this.controleHeight = 0
          this.timer = setTimeout(() => {
            if (this.canRun) this.reqAnimationFrame()
          }, this.waitTime)
          return
        } else {
          // 一次移动高度未达到指定距离继续执行动画
          this.controleHeight += this.speed
        }
      }
      // ====添加滚动间隔控制====结束

      // 当滚动到第一个scroll-item-box高度时scrollBox重置为top:0,视觉上是无缝滚动
      if (this.y >= definedHeight) {
        this.y = 0
      }
      this.myReq = window.requestAnimationFrame(this.reqAnimationFrame)
    }
  }
}
</script>
<style lang="scss">
.scroll-outer {
  height: 100%;
  overflow-x: hidden;
  position: relative;
  &::-webkit-scrollbar {
    width: 0.3vw;
  }
  &:hover::-webkit-scrollbar-track {
    -webkit-box-shadow: inset 0 0 0.1vw rgba(0, 0, 0, 0.3);
    border-radius: 0.1vw;
    background-color: #295099;
    opacity: 1;
    // display: none;
  }
  &:hover::-webkit-scrollbar-thumb {
    opacity: 1;
    border-radius: 0.1vw;
    -webkit-box-shadow: inset 0 0 0.1vw rgba(0, 0, 0, 0.3);
    background-color: #0ba9ea;
  }
}
.scroll-inner-box {
  height: auto;
  position: absolute;
  width: 100%;
  top: 0;
  left: 0;
}
</style>
